package com.hui.server.config.redis;

import com.hui.server.util.ApplicationContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.DigestUtils;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;

/**
 * @BelongsProject: yeb
 * @BelongsPackage: com.hui.server.config.redis
 * @Author: HUI
 * @CreateTime: 2022-04-05 19:47
 * @Description: Redis 实现mybatis 缓存配置
 */
//自定义 Redis 缓存实现
@Slf4j
public class RedisCacheConfig implements Cache {

    /**
     * 当前放入缓存的 mapper 的namespace，就是 mapper 映射类
     */
    private final String id;

    /**
     * 缓存自动过期时间 24小时
     */
    private static final long EXPIRE_TIME_IN_HOURS = 24;

    /**
     * must have a constructor that takes a String id as a parameter
     *
     * @param id
     */
    public RedisCacheConfig(String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        log.info("缓存映射类:{}", id);
        this.id = id;
    }

    @Override
    public String getId() {
        return this.id;
    }

    /**
     * 缓存放入值  redis RedisTemplate   StringRedisTemplate
     *
     * @param key
     * @param value
     */
    @Override
    public void putObject(Object key, Object value) {

        //使用redishash类型作为缓存存储模型  key   hashkey  value
        getRedisTemplate().opsForHash().put(id, getKeyToMD5(key.toString()), value);
        //设置一天超时
        getRedisTemplate().expire(id, 1, TimeUnit.DAYS);

        log.info("Put query result to redis");

      /*  if (id.equals("com.cqm.dao.UserDAO")) {
            //缓存超时  client  用户   client  员工
            getRedisTemplate().expire(id.toString(), 1, TimeUnit.HOURS);
        }


        if (id.equals("com.cqm.dao.CityDAO")) {
            //缓存超时  client  用户   client  员工
            getRedisTemplate().expire(id.toString(), 30, TimeUnit.MINUTES);
        }*/

        //.....指定不同业务模块设置不同缓存超时时间


    }

    /**
     * 从缓存中获取数据
     *
     * @param key
     * @return
     */
    @Override
    public Object getObject(Object key) {
        log.info("Redis需要拿到数据的 key:{}", key.toString());
        return getRedisTemplate().opsForHash().get(id, getKeyToMD5(key.toString()));
    }


    /**
     * 注意:这个方法为mybatis保留方法 默认没有实现 后续版本可能会实现
     *
     * @param key
     * @return
     */
    @Override
    public Object removeObject(Object key) {
        getRedisTemplate().opsForHash().delete(getKeyToMD5(key.toString()));
        log.debug("根据key删除缓存:{}", key);
        return null;
    }

    @Override
    public void clear() {
        log.debug("清空Redis缓存！");
        //清空namespace
        getRedisTemplate().delete(id);//清空缓存
    }

    /**
     * 用来计算缓存数量
     * This method is not used
     * @return
     */
    @Override
    public int getSize() {
        log.info("获取Redis-hash中key value数量");
        return getRedisTemplate().opsForHash().size(id).intValue();
    }

    /**
     * 读写锁
     * @return
     */
    @Override
    public ReadWriteLock getReadWriteLock() {
        return null;
    }

    //封装redisTemplate
    private RedisTemplate<String, Object> getRedisTemplate() {
        //通过application工具类获取redisTemplate
        RedisTemplate<String, Object> redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");


/*      已经配置过Redis的序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());*/
        return redisTemplate;
    }


    //封装一个对key进行md5处理方法
    private String getKeyToMD5(String key) {

        return DigestUtils.md5DigestAsHex(key.getBytes());
    }
}
